package com.framework.aqs;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

/**
 * @author duanzhizhou
 * @date 2025/4/10
 */
public class MyLock {
    
    private boolean fair = false;
    
    private final Node dummy = new Node();
    private final AtomicReference<Node> head = new AtomicReference<>(dummy);
    private final AtomicReference<Node> tail = new AtomicReference<>(dummy);
    
    /**为什么这里不需要volatile修饰？*/
    // AI的解释是owner变量只会由拥有锁的线程查询和修改，所以不需要volatile修饰。
    private Thread owner;
    
    private final AtomicInteger count = new AtomicInteger();
    
    public MyLock(boolean fair) {
        this.fair = fair;
    }
    
    public MyLock() {
    }
    
    public void lock() {
        if (owner == Thread.currentThread()) {
            if (count.incrementAndGet() < 0) {
                throw new RuntimeException("超过最大重入次数");
            }
            return;
        }
        // 第一次加锁
        if (!fair && count.compareAndSet(0, 1)) {
            System.out.println(Thread.currentThread().getName() + "直接拿到锁");
            owner = Thread.currentThread();
            return;
        }
        Node node = new Node();
        while (true) {
            Node preTail = tail.get();
            if (tail.compareAndSet(preTail, node)) {
                System.out.println(Thread.currentThread().getName() + "加入队列，前一个元素是" + preTail.thread.getName());
                preTail.next = node;
                System.out.println(preTail.thread.getName() + "的下一个元素是" + Thread.currentThread().getName());
                System.out.println("head的下一个元素是" + head.get().thread.currentThread().getName());
                node.prev = preTail;
                break;
            }
        }
        while (true) {
            // 第二次加锁
            if (head.get().next == node && count.compareAndSet(0, 1)) {
                System.out.println(Thread.currentThread().getName() + "被唤醒后拿到锁");
                node.prev.next = null;
                node.prev = null;
                head.set(node);
                owner = Thread.currentThread();
                return;
            }
            LockSupport.park();
        }
    }
    
    public void unlock() {
        if (owner != Thread.currentThread()) {
            throw new RuntimeException("当前线程没有持有锁，不能解锁");
        }
        int newCount = count.get() - 1;
        if (newCount == 0) {
            owner = null;
        }
        if (count.decrementAndGet() == 0) {
            // 解锁完成，以下流程会有线程安全问题，注意！！！
            Node next = this.head.get().next;
            if (next != null) {
                System.out.println(Thread.currentThread().getName() + "唤醒了" + next.thread.getName());
                LockSupport.unpark(next.thread);
            }
        }
    }
    
    static class Node {
        volatile Node prev;
        volatile Node next;
        Thread thread;
        
        public Node() {
            this.thread = Thread.currentThread();
        }
    }
}
